package auth

import (
	"errors"
	"time"

	"github.com/golang-jwt/jwt/v5"
)

// JWTSecret 用于签名的密钥
var JWTSecret = []byte("your-secret-key")

// Claims 自定义声明结构体
type Claims struct {
	UserID   int64  `json:"user_id"`
	Username string `json:"username"`
	jwt.RegisteredClaims
}

// GenerateToken 生成token
func GenerateToken(userId int64, username string) (string, error) {
	// 设置过期时间为24小时
	expirationTime := time.Now().Add(24 * time.Hour)

	// 创建声明
	claims := &Claims{
		UserID:   userId,
		Username: username,
		RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(expirationTime),
			IssuedAt:  jwt.NewNumericDate(time.Now()),
			NotBefore: jwt.NewNumericDate(time.Now()),
			Issuer:    "temp",
		},
	}

	// 创建token
	token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

	// 签名并获得完整的编码后的token字符串
	tokenString, err := token.SignedString(JWTSecret)
	return tokenString, err
}

// ParseToken 解析和校验token
func ParseToken(tokenString string) (*Claims, error) {
	// 解析token
	claims := &Claims{}

	token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
		return JWTSecret, nil
	})

	// 校验token
	if err != nil {
		return nil, err
	}

	if !token.Valid {
		return nil, errors.New("invalid token")
	}

	// 检查是否过期
	if claims.ExpiresAt != nil && claims.ExpiresAt.Before(time.Now()) {
		return nil, errors.New("token expired")
	}
	if claims.IssuedAt != nil && claims.IssuedAt.After(time.Now()) {
		return nil, errors.New("token not yet valid")
	}
	if claims.NotBefore != nil && claims.NotBefore.After(time.Now()) {
		return nil, errors.New("token not yet valid")
	}
	if claims.Issuer != "temp" {
		return nil, errors.New("invalid issuer")
	}
	if claims.UserID <= 0 || claims.Username == "" {
		return nil, errors.New("invalid claims")
	}

	return claims, nil
}

// ValidateToken 验证token是否有效，返回bool值
func ValidateToken(tokenString string) bool {
	_, err := ParseToken(tokenString)
	return err == nil
}

// RefreshToken 刷新token
func RefreshToken(tokenString string) (string, error) {
	// 解析token
	claims, err := ParseToken(tokenString)
	if err != nil {
		return "", err
	}

	// 生成新的token
	newToken, err := GenerateToken(claims.UserID, claims.Username)
	return newToken, err
}
